package com.boot.es.service;

import com.alibaba.fastjson.JSON;
import com.boot.es.model.EsProduct;
import com.boot.utils.Result;
import com.boot.utils.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryAction;
import org.elasticsearch.index.reindex.DeleteByQueryRequestBuilder;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;

/**
 * @author zhangsw
 * @Package com.boot.es
 * @date 2020/12/2 17:34
 */
@Service
@Slf4j
public class ProductService {

    @Autowired
    private TransportClient client;

    public Result save(EsProduct product){
        try {
            log.info("添加的数据为：{}", product);
            //参数1:输入索引=mysql的dataBase   参数2：type名称=mysql中的表名
            IndexResponse indexResponse = client.prepareIndex("test_index", "product")
                    .setSource(JSON.toJSONString(product), XContentType.JSON).get();
            //返回查看数据是否成功
            return Result.success(indexResponse);
        }catch (Exception e){
            e.printStackTrace();
            return Result.failure(ResultCode.FAIL);
        }
    }

    public Result saveWithId(EsProduct product){
        try {
            log.info("添加的数据为：{}", product);
            //参数1:输入索引=mysql的dataBase   参数2：type名称=mysql中的表名  参数3：id 相当于主键id
            String id=String.valueOf(product.getProductId());
            IndexResponse indexResponse = client.prepareIndex("test_index", "product",id)
                    .setSource(JSON.toJSONString(product), XContentType.JSON).get();
            //返回查看数据是否成功
            return Result.success(indexResponse);
        }catch (Exception e){
            e.printStackTrace();
            return Result.failure(ResultCode.FAIL);
        }
    }

    public Result deleteByProductId(String productId){
        //根据productId删除对应数据
        DeleteByQueryRequestBuilder builder = DeleteByQueryAction.INSTANCE
                .newRequestBuilder(client)
                .filter(QueryBuilders.termQuery("productId", productId))
                .source("test_index");
        BulkByScrollResponse response = builder.get();
        long deleted = response.getDeleted();
        log.info("删除的条数为：{}",deleted);

        return Result.success(response.toString());
    }

    public Result deleteById(String id){
        try {
            //根据productId删除对应数据
            DeleteResponse result = client.prepareDelete("test_index", "product", id).get();
            if(result.status() == RestStatus.OK){
                return Result.success(result.getResult().toString());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return Result.failure(ResultCode.FAIL);
    }

    public Result deleteByIds(List<String> ids){
        try {

            if (CollectionUtils.isEmpty(ids)){
                return Result.failure(ResultCode.FAIL,null,"id为空");
            }
            BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();
            for(String id:ids){
                //根据productId删除对应数据
                DeleteRequest result = new DeleteRequest("test_index", "product", id);
                bulkRequestBuilder.add(result);
            }
            BulkResponse bulkItemResponses = bulkRequestBuilder.get();

            if(bulkItemResponses.status() == RestStatus.OK){
                return Result.success(bulkItemResponses);
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        return Result.failure(ResultCode.FAIL);
    }

    public Result findById(String id){

        if (id.isEmpty()){
            return Result.failure(ResultCode.FAIL);
        }
        GetResponse result = client.prepareGet("test_index", "product", id).get();
        if (!result.isExists()) {
            return Result.failure(ResultCode.FAIL,null,"不存在");
        }
        return Result.success(result.getSource());

    }

    /** MultiGetRequest */
    public Result findByIds(List<String> ids){

        if (CollectionUtils.isEmpty(ids)){
            return Result.failure(ResultCode.FAIL);
        }

        MultiGetRequest request=new MultiGetRequest();
        for(String id:ids){
            request.add("test_index", "product", id);
        }
        MultiGetResponse multiResponses = null;
        try {
            multiResponses = client.multiGet(request).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        return Result.success(multiResponses);

    }

    /** id批量查询 idsQuery */
    public Result queryIds(List<String> ids){

        if (CollectionUtils.isEmpty(ids)){
            return Result.failure(ResultCode.FAIL);
        }

        IdsQueryBuilder queryBuilder=QueryBuilders.idsQuery("product")
                .addIds((String[])ids.toArray());

        SearchRequestBuilder searchBuilder = client.prepareSearch("test_index")
                .setQuery(queryBuilder);
        SearchResponse searchResponse = searchBuilder.get();

        if(searchResponse.status() == RestStatus.OK){
            SearchHits hits =  searchResponse.getHits();
            return Result.success(hits);
        }
        return Result.failure(ResultCode.FAIL,searchResponse,"查询失败");
    }


    /** 查询所有  match_all */
    public Result findAll(){
        MatchAllQueryBuilder builder= QueryBuilders.matchAllQuery();
        SearchRequestBuilder queryAll = client.prepareSearch("test_index")
                .setQuery(builder)
                .setTypes("product");
        SearchResponse searchResponse = queryAll.get();
        SearchHits hits =  searchResponse.getHits();
        return Result.success(hits);
    }

    /** 查询所有  match 查询 */
    public Result findByTitle(String title){
        MatchQueryBuilder builder = QueryBuilders.matchQuery("title", title);
        SearchRequestBuilder query = client.prepareSearch("test_index")
                .setQuery(builder)
                .setTypes("product");
        SearchResponse searchResponse = query.get();
        SearchHits hits =  searchResponse.getHits();
        return Result.success(hits);
    }

    /** mutilMatch 查询 */
    public Result queryByTitle(String title){

        MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(title,"title","category");
        SearchRequestBuilder searchRequestBuilder = client.prepareSearch("test_index")
                .setQuery(queryBuilder)
                .setTypes("product");
        SearchResponse searchResponse = searchRequestBuilder.get();
        SearchHits hits =  searchResponse.getHits();
        return Result.success(hits);
    }


    /** termsQuery 查询 */
    public Result termsQueryByTitle(List<String> titles){

        String[] title=(String[])titles.toArray();
        TermsQueryBuilder queryBuilder = QueryBuilders.termsQuery("title", title);
        SearchRequestBuilder searchRequestBuilder = client.prepareSearch("test_index")
                .setQuery(queryBuilder)
                .setTypes("product");
        SearchResponse searchResponse = searchRequestBuilder.get();
        SearchHits hits =  searchResponse.getHits();
        return Result.success(hits);

    }

    /** rangeQuery*/
    public Result rangeQuery(String filed,String from,String to){

        log.info("rangeQuery filed={} from={} to={}",filed,from,to);
        QueryBuilder queryBuilder = QueryBuilders.rangeQuery(filed).from(from).to(to);
        //通配符查询 * 零个或多个
//        QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("author","周*");
        //前缀查询
//        QueryBuilder queryBuilder = QueryBuilders.prefixQuery("author","周");
        //模糊查询 查询类型的
//        QueryBuilder queryBuilder = QueryBuilders.fuzzyQuery("id","aac");

        SearchRequestBuilder searchRequestBuilder = client.prepareSearch("test_index")
                .setQuery(queryBuilder)
                .setTypes("product");
        SearchResponse searchResponse = searchRequestBuilder.get();
        if(searchResponse.status() == RestStatus.OK){
            SearchHits hits =  searchResponse.getHits();
            return Result.success(hits);
        }

        return Result.failure(ResultCode.FAIL,searchResponse,"查询失败");
    }

    /**
     *
     * 多条件 组合查询
     */
    public Result boolQuery() throws Exception{

        QueryBuilder queryBuilder=QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("author","周星驰"))
                .mustNot(QueryBuilders.matchQuery("title","梁朝伟"))
                .should(QueryBuilders.matchQuery("title","影帝"))
                .filter(QueryBuilders.rangeQuery("id").gte("1"));

        SearchRequestBuilder searchRequestBuilder = client.prepareSearch("test_index")
                .setTypes("product")
                .setQuery(queryBuilder);

        SearchResponse searchResponse = searchRequestBuilder.get();
        if(searchResponse.status() == RestStatus.OK){
            SearchHits hits =  searchResponse.getHits();
            return Result.success(hits);
        }

        return Result.failure(ResultCode.FAIL,searchResponse,"查询失败");
    }

    public Result findPage(int pageNum,int pageSize){
        int startNum = (pageNum-1)*5;
        SearchResponse searchResponse = client.prepareSearch("test_index")
                .setTypes("product")
                .setQuery(QueryBuilders.matchAllQuery())
                .addSort("id", SortOrder.ASC)
                .setFrom(startNum)
                .setSize(pageSize)
                .get();
        if(searchResponse.status() == RestStatus.OK){
            SearchHits hits =  searchResponse.getHits();
            return Result.success(hits);
        }

        return Result.failure(ResultCode.FAIL,searchResponse,"查询失败");
    }


    public Result updateProduct(EsProduct product){
        log.info("修改的数据为：{}", product);

        try {
            XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
            if(StringUtils.isNotEmpty(product.getBrand())){
                builder.field("brand",product.getBrand());
            }
            if(StringUtils.isNotEmpty(product.getCategory())){
                builder.field("category",product.getCategory());
            }
            if(StringUtils.isNotEmpty(product.getTitle())){
                builder.field("title",product.getTitle());
            }
            if(product.getPrice()>0){
                builder.field("price",product.getPrice());
            }
            if(StringUtils.isNotEmpty(product.getSell_point())){
                builder.field("sell_point",product.getSell_point());
            }
            builder.field("update_time",new Date());
            builder.endObject();
            //输入索引 与type名称
            String id = String.valueOf(product.getProductId());
            UpdateResponse updateResponse = client.prepareUpdate("test_index", "product", id)
                    .setDoc(JSON.toJSONString(product), XContentType.JSON).get();
            if (updateResponse.status() == RestStatus.OK) {
                return Result.success(updateResponse.getResult().toString());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return Result.failure(ResultCode.FAIL);
    }



}
